Skip to content

✨ feat(distances): promote AbstractDistance against ParametricQuantity - #679

Merged
nstarman merged 1 commit into
GalacticDynamics:mainfrom
nstarman:feat/core-distance-parametric-promotion
Aug 8, 2026
Merged

✨ feat(distances): promote AbstractDistance against ParametricQuantity#679
nstarman merged 1 commit into
GalacticDynamics:mainfrom
nstarman:feat/core-distance-parametric-promotion

Conversation

@nstarman

@nstarman nstarman commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

What

The core half of #672. ParametricQuantity is not a unxt.Q subclass, so the AbstractDistance/Q rules in distances/_src/base.py never reached it:

Distance(1, "pc") * PQ(1.0, "rad")  ->  ValueError: Distance must have dimensions length.
PQ(1.0, "rad") * Distance(1, "pc")  ->  PQ(1., 'pc rad')

The operand order decided whether the expression worked. #672 fixed this for coordinaxs.astro's Parallax and DistanceModulus; coordinax.distances.Distance was left with the same defect.

How

  • distances/_src/register_parametric.py — the one add_promotion_rule, and the only file importing unxts.parametric.
  • Imported from distances/_src/__init__.py behind OptDeps.UNXTS_PARAMETRIC.installed.
  • coordinax/_src/optional_deps.py — first Python use of optional-dependencies in core, which was already a declared dependency. Floor moves >=0.3.2>=0.5.0, where members sharing a value no longer silently alias.
  • parametric = ["unxts.parametric>=2.0"] extra.

Overlap with #672

Astro's rules are on Parallax/DistanceModulus, which are AbstractDistance subclasses, so this rule subsumes them. Theirs stay: astro must work against a coordinax predating this, and where both apply plum takes the more specific one. Confirmed the two coexist — all three types give a ParametricQuantity in both operand orders.

Values are unchanged, only reachability. PQ * Distance is PQ(1., 'pc rad') both with and without the new rule; the difference is that Distance * PQ now returns it instead of raising.

Verification

  • tests/: 2153 passed, 6 skipped
  • packages/coordinaxs.astro: 398 passed, 2 skipped (coexistence)
  • Both gate paths exercised: with the distribution hidden from importlib.metadata, coordinax.distances imports without pulling in unxts.parametric, and the new tests skip rather than fail
  • pre-commit (incl. ty): clean

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings August 7, 2026 03:00
@github-actions github-actions Bot added 🔧 Add / update configuration Add or update configuration files. ✅ Add / update / pass tests Add, update, or pass tests. ✨ Introduce new features Introduce new features. labels Aug 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds an optional promotion rule so AbstractDistance interoperates consistently with unxts.parametric.ParametricQuantity, fixing operand-order-dependent behavior and wiring the registration behind an optional dependency gate.

Changes:

  • Register a Plum promotion rule between AbstractDistance and ParametricQuantity when unxts.parametric is installed.
  • Introduce a small internal optional-dependency enum (OptDeps) and bump optional-dependencies floor to support it safely.
  • Add test coverage to verify promotion + order-independent arithmetic under the optional install.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/distances/test_parametric_promotion.py Adds tests exercising the optional registration and ensuring Distance * PQ works.
src/coordinax/distances/_src/register_parametric.py Defines the AbstractDistanceParametricQuantity promotion rule.
src/coordinax/distances/_src/init.py Conditionally imports the parametric registration based on OptDeps.
src/coordinax/_src/optional_deps.py Adds internal OptDeps enum wrapper around optional-dependencies.
pyproject.toml Raises optional-dependencies minimum version and adds a parametric extra.

Comment thread src/coordinax/distances/_src/__init__.py
Comment thread tests/unit/distances/test_parametric_promotion.py Outdated
@nstarman
nstarman force-pushed the feat/core-distance-parametric-promotion branch from 76703bd to 4b4d04c Compare August 8, 2026 00:08
@codecov

codecov Bot commented Aug 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.12%. Comparing base (71b9ec7) to head (09532d8).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #679   +/-   ##
=======================================
  Coverage   96.12%   96.12%           
=======================================
  Files         254      254           
  Lines        8179     8182    +3     
=======================================
+ Hits         7862     7865    +3     
  Misses        317      317           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…tity`

`ParametricQuantity` is not a `unxt.Q` subclass, so the `AbstractDistance`/`Q`
promotion rules in `distances/_src/base.py` never reach it.
`Distance(1, "pc") * PQ(1.0, "rad")` dispatches to the `Distance`-returning
multiply and raises `Distance must have dimensions length`, while the mirrored
`PQ * Distance` returns a `PQ` -- the operand order decides whether the
expression works.

The rule goes in the existing `register_parametric`, already imported behind
`OptDeps.UNXTS_PARAMETRIC.installed`, and spells the type `PQ` to match the
`from_` overloads above it -- `PQ is ParametricQuantity`. Adds the matching
`parametric` extra, which the module had been relying on the test group to
supply.

This is the core half of GalacticDynamics#672, which fixed the same defect for
`coordinaxs.astro`'s `Parallax` and `DistanceModulus`. Those are
`AbstractDistance` subclasses, so this subsumes them; astro's stay, since it
must work against a `coordinax` predating this, and plum takes the more
specific rule where both apply.

Only reachability changes, not values: `PQ * Distance` is `PQ(1., 'pc rad')`
before and after, and `Distance * PQ` now returns that instead of raising.

`tests/unit/distances`: 66 passed. `packages/coordinaxs.astro`: 406 passed, 2
skipped. With the distribution hidden from `importlib.metadata`,
`coordinax.distances` imports without pulling in `unxts.parametric`.
pre-commit clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nstarman
nstarman force-pushed the feat/core-distance-parametric-promotion branch from 4b4d04c to 09532d8 Compare August 8, 2026 01:28
@nstarman nstarman added this to the v0.24.0 milestone Aug 8, 2026
@nstarman
nstarman merged commit 9cd8a33 into GalacticDynamics:main Aug 8, 2026
18 checks passed
@nstarman
nstarman deleted the feat/core-distance-parametric-promotion branch August 8, 2026 02:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔧 Add / update configuration Add or update configuration files. ✅ Add / update / pass tests Add, update, or pass tests. ✨ Introduce new features Introduce new features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants